package com.bike.bikeserver.service.impl;

import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.bike.bikeserver.common.core.domain.CommonResult;
import com.bike.bikeserver.common.utils.ModelUtils;
import com.bike.bikeserver.domain.BikeDispatch;
import com.bike.bikeserver.domain.BikeRequest;
import com.bike.bikeserver.domain.WXUser;
import com.bike.bikeserver.domain.vo.BikeRequestVo;
import com.bike.bikeserver.domain.vo.HistoryInfoVo;
import com.bike.bikeserver.domain.vo.RequestProcessVo;
import com.bike.bikeserver.mapper.BikeDispatchMapper;
import com.bike.bikeserver.mapper.BikeRequestMapper;
import com.bike.bikeserver.mapper.WXUserMapper;
import com.bike.bikeserver.service.IBikeRequestService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import static com.bike.bikeserver.constant.Constants.*;
import static com.bike.bikeserver.constant.ModelParamConstant.DEEPLAB_NO_OV_PARK_JUDGE_URL;
import static com.bike.bikeserver.constant.ModelParamConstant.YOLO_NO_OV_URL;

/**
 * @version 1.0
 * @Author ZZX
 * @Date 2023/7/9 22:07
 */
@Service
public class BikeRequestServiceImpl implements IBikeRequestService
{
    @Autowired
    BikeRequestMapper bikeRequestMapper;
    @Autowired
    BikeDispatchMapper bikeDispatchMapper;
    @Autowired
    WXUserMapper wxUserMapper;

    /**
     * 处理单车淤积、乱停乱放情况
     *
     * @param bikeRequestVo
     * @return
     */
    @Override
    public CommonResult sendRequest(BikeRequestVo bikeRequestVo)
    {
        // 首先根据用户名称和请求类型判断是否该用户已经有一个未处理的请求，如果有，则返回错误值
        LambdaQueryWrapper<BikeRequest> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(BikeRequest::getRequestApplier, bikeRequestVo.getNickName());
        wrapper.eq(BikeRequest::getRequestType, bikeRequestVo.getRequestType());
        BikeRequest one = bikeRequestMapper.selectOne(wrapper);
        if (one != null && UNHANDLED_STATE.equals(one.getRequestState()))
        {
            return CommonResult.error("您有一个未处理的" + bikeRequestVo.getRequestType() + "请求，请先等待该请求被处理后，再发送新的请求！");
        }
        // 根据已有信息组装BikeRequest对象属性值，并入库
        BikeRequest bikeRequest = new BikeRequest();
        bikeRequest.setZoneName(bikeRequestVo.getLocName());
        bikeRequest.setRequestApplier(bikeRequestVo.getNickName());
        bikeRequest.setRequestType(bikeRequestVo.getRequestType());
        JSONObject requestContent = new JSONObject();
        requestContent.put("bikeName", bikeRequestVo.getBikeName());
        requestContent.put("locName", bikeRequestVo.getLocName());
        requestContent.put("locRoad", bikeRequestVo.getLocRoad());
        requestContent.put("locImg", bikeRequestVo.getLocImg());
        requestContent.put("sendTime", bikeRequestVo.getSendTime());
        requestContent.put("personalTxt", bikeRequestVo.getPersonalTxt());
        bikeRequest.setRequestContent(requestContent.toString());
        /*
            如果存在多张图片，一张说明存在单车淤积，判定属于这个情况
            但是为了速度，就一张吧。
         */
        // 如果是【单车淤积】，调用yolov5接口，检查图片单车数量是否超过固定数量（加载枚举类里，暂且设为20吧，后续可以搞在字典里，加一张表，后续优化时做）
        boolean ifOk = false;
        if (BIKE_SILTATION.equals(bikeRequestVo.getRequestType()))
        {
            List<String> locImg = bikeRequestVo.getLocImg();
            for (String img : locImg)
            {
                JSONObject params = new JSONObject();
                ArrayList<String> imageCodes = new ArrayList<>();
                imageCodes.add(img);
                params.put("imageCodes", imageCodes);
                String yoloResult = ModelUtils.getYoloResult(YOLO_NO_OV_URL, params);
                bikeRequest.setRequestResult(yoloResult);
                if (ModelUtils.judgeIfTooManyBikes(yoloResult))
                {
                    ifOk = true;
                    break;
                }
            }
        }
        // 反之就是【乱停乱放】，调用接口返回是否属实
        else
        {
            List<String> locImg = bikeRequestVo.getLocImg();
            for (String img : locImg)
            {
                JSONObject params = new JSONObject();
                params.put("imageCode", img);
                String deepLabV3Result = ModelUtils.getDeepLabV3Result(DEEPLAB_NO_OV_PARK_JUDGE_URL, params);
                bikeRequest.setRequestResult(deepLabV3Result);
                if (ModelUtils.judgeIfParkingWrongly(deepLabV3Result))
                {
                    ifOk = true;
                    break;
                }
            }
        }
        if (ifOk)
        {
            bikeRequest.setRequestState(UNHANDLED_STATE);
            int insert = bikeRequestMapper.insert(bikeRequest);
            // 更新用户的积分数
            LambdaQueryWrapper<WXUser> wrapper_wxuser = new LambdaQueryWrapper<>();
            wrapper_wxuser.eq(WXUser::getNickName, bikeRequestVo.getNickName());
            WXUser wxUser = wxUserMapper.selectOne(wrapper_wxuser);
            if (PARKING_RANDOMLY.equals(bikeRequestVo.getRequestType()))
            {
                wxUser.setRewardsNum(wxUser.getRewardsNum() + PARKING_SCORE);
                wxUserMapper.updateById(wxUser);
                return CommonResult.success("发送成功！同时您获得" + PARKING_SCORE + "积分", insert);
            }
            else
            {
                wxUser.setRewardsNum(wxUser.getRewardsNum() + SILTATION_SCORE);
                wxUserMapper.updateById(wxUser);
                return CommonResult.success("发送成功！同时您获得" + SILTATION_SCORE + "积分", insert);
            }
        }
        else
        {
            bikeRequest.setRequestState(NO_NEED_TO_HANDLE);
            int insert = bikeRequestMapper.insert(bikeRequest);
            return CommonResult.success("发送成功！但很抱歉，情况不属实，无法给您积分奖励！");
        }

    }

    @Override
    public CommonResult applyDispatchRequest(BikeRequestVo bikeRequestVo)
    {
        // 首先根据用户名称和请求类型判断是否该用户已经有一个未处理的请求，如果有，则返回错误值
        LambdaQueryWrapper<BikeRequest> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(BikeRequest::getRequestApplier, bikeRequestVo.getNickName());
        wrapper.eq(BikeRequest::getRequestType, bikeRequestVo.getRequestType());
        wrapper.eq(BikeRequest::getRequestState, UNHANDLED_STATE);
        BikeRequest one = bikeRequestMapper.selectOne(wrapper);
        if (one != null && UNHANDLED_STATE.equals(one.getRequestState()))
        {
            return CommonResult.error("您有一个未处理的" + bikeRequestVo.getRequestType() + "请求，请先等待该请求被处理后，再发送新的请求！");
        }

        // 根据已有信息组装BikeRequest对象属性值
        BikeRequest bikeRequest = new BikeRequest();
        bikeRequest.setZoneName(bikeRequestVo.getLocName());
        bikeRequest.setRequestApplier(bikeRequestVo.getNickName());
        bikeRequest.setRequestType(bikeRequestVo.getRequestType());
        JSONObject requestContent = new JSONObject();
        requestContent.put("locName", bikeRequestVo.getLocName());
        requestContent.put("locImg", bikeRequestVo.getLocImg());
        bikeRequest.setRequestContent(requestContent.toString());

        // 分别调用单车淤积和乱停乱放判断接口，存在一种情况就视为值得调度
        boolean ifOk = false;
        String resText = "";
        List<String> locImg = bikeRequestVo.getLocImg();
        for (String img : locImg)
        {
            // 判断是否存在单车淤积
            JSONObject params1 = new JSONObject();
            ArrayList<String> imageCodes = new ArrayList<>();
            imageCodes.add(img);
            params1.put("imageCodes", imageCodes);
            String yoloResult = ModelUtils.getYoloResult(YOLO_NO_OV_URL, params1);
            bikeRequest.setRequestResult(yoloResult);
            if (ModelUtils.judgeIfTooManyBikes(yoloResult))
            {
                ifOk = true;
                resText = yoloResult;
                break;
            }
            // 判断是否存在乱停乱放
            JSONObject params2 = new JSONObject();
            params2.put("imageCode", img);
            String deepLabV3Result = ModelUtils.getDeepLabV3Result(DEEPLAB_NO_OV_PARK_JUDGE_URL, params2);
            bikeRequest.setRequestResult(deepLabV3Result);
            if (ModelUtils.judgeIfParkingWrongly(deepLabV3Result))
            {
                ifOk = true;
                resText = deepLabV3Result;
                break;
            }
        }
        if (ifOk)
        {
            bikeRequest.setRequestType(resText);
            bikeRequest.setRequestState(UNHANDLED_STATE);
            bikeRequestMapper.insert(bikeRequest);
            BikeDispatch bikeDispatch = new BikeDispatch();
            bikeDispatch.setZoneName(bikeRequestVo.getLocName());
            bikeDispatch.setDispatchImgUrl(bikeRequestVo.getLocImg().get(0));
            bikeDispatch.setDispatchApplier(bikeRequestVo.getNickName());
            bikeDispatch.setDispatchState(UNHANDLED_STATE);
            bikeDispatchMapper.insert(bikeDispatch);
            // 更新用户的积分数
            LambdaQueryWrapper<WXUser> wrapper_wxuser = new LambdaQueryWrapper<>();
            wrapper_wxuser.eq(WXUser::getNickName, bikeRequestVo.getNickName());
            WXUser wxUser = wxUserMapper.selectOne(wrapper_wxuser);
            wxUser.setRewardsNum(wxUser.getRewardsNum() + APPLY_SCORE);
            wxUserMapper.updateById(wxUser);
            return CommonResult.success("发送成功！同时您获得" + APPLY_SCORE + "积分");
        }
        else
        {
            bikeRequest.setRequestState(NO_NEED_TO_HANDLE);
            bikeRequestMapper.insert(bikeRequest);
            BikeDispatch bikeDispatch = new BikeDispatch();
            bikeDispatch.setZoneName(bikeRequestVo.getLocName());
            bikeDispatch.setDispatchImgUrl(bikeRequestVo.getLocImg().get(0));
            bikeDispatch.setDispatchApplier(bikeRequestVo.getNickName());
            bikeDispatch.setDispatchState(NO_NEED_TO_HANDLE);
            bikeDispatchMapper.insert(bikeDispatch);
            return CommonResult.success("发送成功！但很抱歉，情况不属实，无法给您积分奖励！");
        }
    }

    @Override
    public CommonResult getRequestListByNickName(String nickName)
    {
        // 获取requestListOfBikeSiltation
        List<RequestProcessVo> requestListOfBikeSiltation = getRequestProcessListOfOnes(nickName, BIKE_SILTATION, "提交淤积预警", DONE_LOGO, SUBMIT_LOGO);
        List<RequestProcessVo> requestListOfBikeDispatch = getRequestProcessListOfOnes(nickName, BIKE_DISPATCH, "申请调度", DISPATCH_LOGO, APPLY_LOGO);
        Map<String, List<RequestProcessVo>> map = new HashMap<>();
        map.put("bikeSiltation", requestListOfBikeSiltation);
        map.put("bikeDispatch", requestListOfBikeDispatch);
        return CommonResult.success(map);
    }

    @Override
    public CommonResult getRequestsByNickName(String nickName)
    {
        LambdaQueryWrapper<BikeRequest> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(BikeRequest::getRequestApplier, nickName);
        List<BikeRequest> bikeRequests = bikeRequestMapper.selectList(wrapper);
        // 转换成historyInfo列表格式
        List<HistoryInfoVo> historyInfoVoList = new ArrayList<>();
        for (BikeRequest bikeRequest : bikeRequests)
        {
            HistoryInfoVo historyInfoVo = new HistoryInfoVo();
            historyInfoVo.setTime(bikeRequest.getUpdateTime());
            historyInfoVo.setName("处理地区：" + bikeRequest.getZoneName());
            historyInfoVo.setInfo(bikeRequest.getRequestResult());
            historyInfoVo.setState("请求类型：" + bikeRequest.getRequestType() + "；处理状态：" + bikeRequest.getRequestState());
            historyInfoVoList.add(historyInfoVo);
        }
        return CommonResult.success(historyInfoVoList);
    }

    @Override
    public CommonResult getBikeRequestList()
    {
        List<BikeRequest> bikeRequests = bikeRequestMapper.selectList(null);
        return CommonResult.success(bikeRequests);
    }

    @Override
    public CommonResult editBikeRequestById(BikeRequest bikeRequest)
    {
        // 只允许修改请求类型或者区域名称
        BikeRequest bikeRequest1 = bikeRequestMapper.selectById(bikeRequest.getId());
        if (bikeRequest1.getRequestType().equals(bikeRequest.getRequestType()) && bikeRequest1.getZoneName().equals(bikeRequest.getZoneName()))
        {
            return CommonResult.warn("请勿输入空值或重复修改！");
        }
        bikeRequest1.setRequestType(bikeRequest.getRequestType());
        bikeRequest1.setZoneName(bikeRequest.getZoneName());
        int update = bikeRequestMapper.updateById(bikeRequest1);
        if (update != 0)
        {
            return CommonResult.success("修改成功！");
        }
        return CommonResult.error();
    }

    @Override
    public CommonResult deleteBikeRequestById(BikeRequest bikeRequest)
    {
        int count = bikeRequestMapper.deleteById(bikeRequest.getId());
        if (count != 0)
        {
            return CommonResult.success("已成功删除！");
        }
        return CommonResult.error();
    }

    @Override
    public CommonResult getBikeRequestByNameOfBack(String requestApplier)
    {
        LambdaQueryWrapper<BikeRequest> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(BikeRequest::getRequestApplier, requestApplier);
        List<BikeRequest> bikeRequests = bikeRequestMapper.selectList(wrapper);
        return CommonResult.success("查询成功！为您找到" + bikeRequests.size() + "条记录！", bikeRequests);
    }

    @Override
    public CommonResult applyRequestToDispatch(BikeRequest bikeRequest)
    {
        // 更新单车请求状态
        bikeRequest.setRequestResult("已移交至调度列表");
        bikeRequest.setRequestState(COMPLETED);
        bikeRequestMapper.updateById(bikeRequest);

        return CommonResult.success("已成功将该请求移交至调度列表！");
    }

    private List<RequestProcessVo> getRequestProcessListOfOnes(String nickName, String type, String applyInfo, String sc, String fa)
    {
        // 获取单车淤积的未处理的记录（必为单条）
        LambdaQueryWrapper<BikeRequest> wrapper_bikeRequest1 = new LambdaQueryWrapper<>();
        wrapper_bikeRequest1.eq(BikeRequest::getRequestApplier, nickName);
        wrapper_bikeRequest1.eq(BikeRequest::getRequestType, type);
        wrapper_bikeRequest1.eq(BikeRequest::getRequestState, UNHANDLED_STATE);
        BikeRequest bikeRequest1 = bikeRequestMapper.selectOne(wrapper_bikeRequest1);
        if (bikeRequest1 != null)
        {
            List<RequestProcessVo> lists = new ArrayList<>();
            RequestProcessVo requestProcessVo1 = new RequestProcessVo();
            requestProcessVo1.setRequestTime(bikeRequest1.getCreateTime());
            requestProcessVo1.setRequestInfo(applyInfo + "(" + bikeRequest1.getZoneName() + ")");/**/
            requestProcessVo1.setRequestState(fa);
            RequestProcessVo requestProcessVo2 = new RequestProcessVo();
            requestProcessVo2.setRequestTime(bikeRequest1.getCreateTime());
            requestProcessVo2.setRequestInfo("请求尚在处理");/**/
            requestProcessVo2.setRequestState(sc);
            lists.add(requestProcessVo1);
            lists.add(requestProcessVo2);
            return lists;
        }
        else
        {
            List<RequestProcessVo> lists = new ArrayList<>();
            LambdaQueryWrapper<BikeRequest> wrapper_bikeRequest2 = new LambdaQueryWrapper<>();
            wrapper_bikeRequest2.eq(BikeRequest::getRequestApplier, nickName);
            wrapper_bikeRequest2.eq(BikeRequest::getRequestType, type);
            wrapper_bikeRequest2.orderByDesc(BikeRequest::getCreateTime);
            List<BikeRequest> bikeRequests = bikeRequestMapper.selectList(wrapper_bikeRequest2);
            if (bikeRequests.size() > 0)
            {
                BikeRequest bikeRequest2 = bikeRequests.get(0);
                RequestProcessVo requestProcessVo3 = new RequestProcessVo();
                requestProcessVo3.setRequestTime(bikeRequest2.getCreateTime());
                requestProcessVo3.setRequestInfo(applyInfo + "(" + bikeRequest2.getZoneName() + ")");/**/
                requestProcessVo3.setRequestState(fa);
                RequestProcessVo requestProcessVo4 = new RequestProcessVo();
                requestProcessVo4.setRequestTime(bikeRequest2.getUpdateTime());
                requestProcessVo4.setRequestInfo(bikeRequest2.getRequestResult() + "(" + bikeRequest2.getZoneName() + ")");/**/
                requestProcessVo4.setRequestState(sc);
                lists.add(requestProcessVo3);
                lists.add(requestProcessVo4);
                return lists;
            }
            else
            {
                RequestProcessVo requestProcessVo5 = new RequestProcessVo();
                requestProcessVo5.setRequestTime(null);
                requestProcessVo5.setRequestInfo("暂无请求");
                requestProcessVo5.setRequestState(fa);
                lists.add(requestProcessVo5);
                requestProcessVo5.setRequestState(sc);
                lists.add(requestProcessVo5);
                return lists;
            }
        }
    }


}